import { ControlVOBase } from '@/core';
import {
	EditFormActionType,
	ICtrlActionResult,
	IEditFormAbility,
	IHttpResponse,
	IParam,
	IWizardPanelAbility,
	IWizardPanelController,
	IWizardPanelControllerParams,
	IWizardPanelModel,
	IWizardPanelStore,
	WizardPanelActionType,
} from '@/core/interface';
import WizardPanelService from '@/core/modules/ctrl-service/wizard-panel-service';
import { deepCopy } from '@/core/utils';
import { DECtrlController } from './de-ctrl-controller';

/**
 * 向导面板部件控制器
 *
 * @export
 * @class WizardPanelController
 * @extends {DECtrlController<WizardPanelActionType, IWizardPanelStore, IWizardPanelAbility>}
 * @implements {IWizardPanelController<IWizardPanelStore, IWizardPanelAbility>}
 */
export class WizardPanelController
	extends DECtrlController<
		WizardPanelActionType,
		IWizardPanelStore,
		IWizardPanelAbility
	>
	implements IWizardPanelController<IWizardPanelStore, IWizardPanelAbility>
{
	/**
	 * 向导面板模型
	 *
	 * @type {IWizardPanelModel}
	 * @memberof WizardPanelController
	 */
	protected declare model: IWizardPanelModel;

	/**
	 * 部件服务
	 *
	 * @type {FormService<ControlVOBase>}
	 * @memberof WizardPanelController
	 */
	declare ctrlService: WizardPanelService<ControlVOBase>;

	/**
	 * Creates an instance of WizardPanelController.
	 * @param {IWizardPanelControllerParams<WizardPanelActionType, IWizardPanelAbility>} params
	 * @memberof WizardPanelController
	 */
	public constructor(
		params: IWizardPanelControllerParams<
			WizardPanelActionType,
			IWizardPanelAbility
		>
	) {
		super(params);
		this.ctrlInit(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param {(IWizardPanelControllerParams<WizardPanelActionType, IWizardPanelAbility>)} params
	 * @memberof WizardPanelController
	 */
	protected processCtrlInit(
		params: IWizardPanelControllerParams<
			WizardPanelActionType,
			IWizardPanelAbility
		>
	): void {
		super.processCtrlInit(params);
		Object.assign(this.store, {
			activeEditForm: {},
			stepTags: {},
			steps: [],
		});
		if (this.actions.initAction) {
			this.initAction = this.actions.initAction;
		}
		if (this.actions.finishAction) {
			this.finishAction = this.actions.finishAction;
		}
		if (this.model.stateField) {
			this.stateField = this.model.stateField.toLowerCase();
		}
		this.isStateWizard = this.model.isStateWizard;
		this.initActiveForm();
		this.regFormActions();
	}

	/**
	 * 部件行为--init
	 *
	 * @type {string}
	 * @memberof WizardPanelController
	 */
	public initAction = '';

	/**
	 * 部件行为--finish
	 *
	 * @type {string}
	 * @memberof WizardPanelController
	 */
	public finishAction = '';

	/**
	 * 当前激活Wizard表单
	 * `${this.model.name}_form_${this.formParam['srfnextform'].toLowerCase()}`
	 *
	 * @type {string}
	 * @memberof WizardPanelController
	 */
	public activeForm = '';

	/**
	 * 执行过的表单
	 *
	 * @public
	 * @type {Array<string>}
	 * @memberof WizardPanelController
	 */
	public historyForms: Array<string> = [];

	/**
	 * 步骤集合
	 *
	 * @type {*}
	 * @memberof WizardPanelController
	 */
	public steps: Array<IParam> = [];

	/**
	 * 步骤行为集合
	 *
	 * @type {*}
	 * @memberof WizardPanelController
	 */
	public stepActions: any = {};

	/**
	 * 向导表单集合
	 *
	 * @type {Array<any>}
	 * @memberof WizardPanelController
	 */
	public wizardForms: Array<any> = [];

	/**
	 * 当前状态
	 *
	 * @memberof WizardPanelController
	 */
	public curState = '';

	/**
	 * 向导表单参数
	 *
	 * @type {*}
	 * @memberof WizardPanelController
	 */
	public formParam: any = {};

	/**
	 * 是否为状态向导
	 *
	 * @type {string}
	 * @memberof WizardPanelController
	 */
	public isStateWizard = false;

	/**
	 * 状态属性
	 *
	 * @type {string}
	 * @memberof WizardPanelController
	 */
	public stateField = '';

	/**
	 * 首表单
	 *
	 * @type {string}
	 * @memberof StateWizardPanelControlBase
	 */
	public firstForm = '';

	/**
	 * 初始化当前激活表单
	 *
	 * @memberof WizardPanelController
	 */
	public initActiveForm() {
		const wizardForms = this.model.wizardForms || [];
		if (wizardForms.length > 0) {
			const firstForm = wizardForms.find((form: any) => {
				return form.firstForm;
			});
			if (firstForm) {
				this.firstForm = firstForm.editFormName;
				// 常规向导初始化时取第一个表单为激活表单
				if (!this.isStateWizard) {
					this.activeForm = this.firstForm;
					this.getActiveEditForm(this.activeForm);
					this.historyForms.push(this.activeForm);
				}
			}
		}
	}

	/**
	 * 注册表单步骤行为
	 *
	 * @memberof WizardPanelController
	 */
	public regFormActions() {
		const wizardForms = this.model.wizardForms || [];
		const wizardSteps = this.model.wizardSteps || [];
		if (wizardForms.length > 0) {
			wizardForms.forEach((stepForm: any) => {
				const formName = stepForm.editFormName;
				const editForm = (this.model.editForms || []).find((form: any) => {
					return form.name === formName;
				});
				const action = {
					loadAction: editForm?.actions.loadAction || 'Get',
					preAction: editForm?.actions.preAction,
					saveAction: editForm?.actions.updateAction || 'Update',
					actions: stepForm.stepActions || [],
				};
				this.regFormAction(
					formName,
					action,
					this.getStepTag(wizardSteps, stepForm.stepTag)
				);
			});
		}
		if (wizardSteps.length > 0) {
			wizardSteps.forEach((steps: any) => {
				this.steps.push(steps.stepTag);
			});
		}
	}

	/**
	 * 注册表单步骤行为
	 *
	 * @memberof WizardPanelController
	 */
	public regFormAction(name: string, actionParams: any, stepTag: any) {
		this.stepActions[name] = actionParams;
		this.store.stepTags[name] = stepTag;
		this.wizardForms.push(name);
	}

	/**
	 * 获取步骤标识
	 *
	 * @memberof WizardPanelController
	 */
	public getStepTag(wizardSteps: Array<any>, tag: string) {
		if (wizardSteps && wizardSteps.length > 0 && tag) {
			const curStep: any = wizardSteps.find((step: any) => {
				return step.stepTag === tag;
			});
			return curStep.stepTag || tag;
		} else {
			return tag;
		}
	}

	/**
	 * 上一步
	 *
	 * @memberof WizardPanelController
	 */
	public clickPrev() {
		const length = this.historyForms.length;
		if (length > 1) {
			this.curState = 'PREV';
			if (this.stepActions[this.activeForm].preAction) {
				const ability = this.getFormAbility(this.activeForm);
				if (ability) {
					ability.panelAction(
						this.stepActions[this.activeForm].preAction,
						'save',
						this.formParam
					);
				}
			} else {
				this.activeForm = this.historyForms[length - 2];
				this.getActiveEditForm(this.activeForm);
				setTimeout(() => {
					this.formLoad();
				}, 1);
				this.historyForms.splice(length - 1, 1);
			}
		}
	}

	/**
	 * 下一步
	 *
	 * @memberof WizardPanelController
	 */
	public clickNext() {
		if (this.activeForm) {
			const ability = this.getFormAbility(this.activeForm);
			if (ability) {
				ability
					.validate()
					.then((res: any) => {
						if (res === false) {
							App.getNotificationHelper().error(
								App.ts('app.notificationtitle.error', '错误'),
								App.ts('widget.editform.formvalidate', '表单校验失败')
							);
						} else {
							this.curState = 'NEXT';
							ability.panelAction(
								this.stepActions[this.activeForm].saveAction,
								'save',
								this.formParam
							);
						}
					})
					.catch(() => {
						App.getNotificationHelper().error(
							App.ts('app.notificationtitle.error', '错误'),
							App.ts('widget.editform.formvalidate', '表单校验失败')
						);
					});
			}
		}
	}

	/**
	 * 完成
	 *
	 * @memberof WizardPanelController
	 */
	public clickFinish() {
		if (this.activeForm) {
			const ability = this.getFormAbility(this.activeForm);
			if (ability) {
				ability
					.validate()
					.then((res: any) => {
						if (res === false) {
							App.getNotificationHelper().error(
								App.ts('app.notificationtitle.error', '错误'),
								App.ts('widget.editform.valueruleabnormal', '值规则异常')
							);
						} else {
							this.curState = 'FINISH';
							ability.panelAction(
								this.stepActions[this.activeForm].saveAction,
								'save',
								this.formParam
							);
						}
					})
					.catch(() => {
						App.getNotificationHelper().error(
							App.ts('app.notificationtitle.error', '错误'),
							App.ts('widget.editform.valueruleabnormal', '值规则异常')
						);
					});
			}
		}
	}

	/**
	 * 向导表单加载完成
	 *
	 * @param {*} args
	 * @param {string} name
	 * @memberof WizardPanelController
	 */
	public wizardpanelFormload(args: any, name: string) {
		if (args) {
			Object.assign(this.formParam, args);
		}
	}

	/**
	 * 向导表单保存完成
	 *
	 * @param {*} args
	 * @param {string} name
	 * @memberof WizardPanelController
	 */
	public wizardpanelFormsave(args: any, name: string) {
		Object.assign(this.formParam, args);
		if (Object.is(this.curState, 'NEXT')) {
			if (this.getNextForm()) {
				this.activeForm = this.getNextForm();
				this.getActiveEditForm(this.activeForm);
				setTimeout(() => {
					this.formLoad();
				}, 1);
				this.historyForms.push(this.activeForm);
			} else {
				this.doFinish();
			}
		} else if (Object.is(this.curState, 'PREV')) {
			const length = this.historyForms.length;
			if (length > 1) {
				this.activeForm = this.historyForms[length - 2];
				this.getActiveEditForm(this.activeForm);
				setTimeout(() => {
					this.formLoad();
				}, 1);
				this.historyForms.splice(length - 1, 1);
			}
		} else if (Object.is(this.curState, 'FINISH')) {
			this.doFinish();
		}
	}

	/**
	 * 获取下一步向导表单
	 *
	 * @memberof WizardPanelController
	 */
	public getNextForm() {
		if (this.formParam && this.formParam[this.stateField]) {
			if (Object.keys(this.store.stepTags).length > 0) {
				let formName = '';
				Object.keys(this.store.stepTags).forEach((name: string) => {
					if (this.store.stepTags[name] === this.formParam[this.stateField]) {
						formName = name;
					}
				});
				return formName;
			}
		} else if (this.formParam && this.formParam['srfnextform']) {
			return `${this.model.name}_form_${this.formParam[
				'srfnextform'
			].toLowerCase()}`;
		} else {
			const index = this.wizardForms.indexOf(this.activeForm);
			if (index >= 0) {
				if (this.wizardForms[index + 1]) {
					return this.wizardForms[index + 1];
				}
			}
			return undefined;
		}
	}

	/**
	 * 完成行为
	 *
	 * @memberof WizardPanelController
	 */
	public doFinish() {
		const arg: any = {};
		Object.assign(arg, this.formParam);
		Object.assign(arg, { viewParams: this.store.viewParams });
		const tempContext: any = deepCopy(this.store.context);
		this.beforeAsyncAction('doFinish', tempContext, arg);
		const post: Promise<any> = this.ctrlService.finish(
			this.finishAction,
			tempContext,
			arg
		);
		post
			.then((response: any) => {
				this.afterAsyncAction('doFinish', response);
				if (response.success) {
					const data = response.data;
					this.emit('doFinish', data);
				} else {
					App.getNotificationHelper().error(
						App.ts('app.notificationtitle.error', '错误'),
						response
					);
				}
			})
			.catch((response: any) => {
				this.afterAsyncAction('doFinish', response);
				App.getNotificationHelper().error(
					App.ts('app.notificationtitle.error', '错误'),
					response
				);
			});
	}

	/**
	 * 计算激活表单
	 *
	 * @param {*} data 数据
	 * @memberof StateWizardPanelControlBase
	 */
	public computedActiveForm(data: any) {
		if (data[this.stateField]) {
			if (Object.keys(this.store.stepTags).length > 0) {
				Object.keys(this.store.stepTags).forEach((name: string) => {
					if (this.store.stepTags[name] === data[this.stateField]) {
						this.activeForm = name;
					}
				});
			}
			if (!this.activeForm) {
				this.activeForm = this.firstForm;
			}
		} else {
			this.activeForm = this.firstForm;
		}
		if (this.activeForm) {
			const index = this.wizardForms.indexOf(this.activeForm);
			this.wizardForms.forEach((item: any, inx: number) => {
				if (inx <= index) {
					this.historyForms.push(item);
				}
			});
			this.getActiveEditForm(this.activeForm);
		}
	}

	/**
	 * 加载数据 doInit
	 *
	 * @param {IParam} [opts={}]
	 * @return {*}  {Promise<ICtrlActionResult>}
	 * @memberof WizardPanelController
	 */
	async load(opts: IParam = {}): Promise<ICtrlActionResult> {
		const arg: any = { ...opts };
		Object.assign(arg, { viewParams: this.store.viewParams });
		const tempContext: any = deepCopy(this.store.context);
		this.beforeAsyncAction('load', tempContext, arg);
		try {
			const response: IHttpResponse = await this.ctrlService.init(
				this.initAction,
				tempContext,
				arg
			);
			this.afterAsyncAction('load', response);
			if (!response.success) {
				return {
					ok: false,
					data: [],
					rowData: response,
				};
			}
			this.formParam = response.data;
			const appDeCodeName = this.model.entityCodeName;
			if (appDeCodeName && response.data[appDeCodeName.toLowerCase()]) {
				Object.assign(this.store.context, {
					[appDeCodeName.toLowerCase()]:
						response.data[appDeCodeName.toLowerCase()],
				});
			}
			if (this.isStateWizard) {
				// 状态向导根据返回数据中的状态属性决定激活哪个表单
				this.computedActiveForm(this.formParam);
			}
			this.formLoad();
			this.emit('load', response.data);
			return {
				ok: true,
				data: [],
				rowData: response,
			};
		} catch (error: any) {
			this.afterAsyncAction('load', error);
			return {
				ok: false,
				data: [],
				rowData: error,
			};
		}
	}

	/**
	 * 表单加载
	 *
	 * @memberof WizardPanelController
	 */
	public formLoad() {
		if (this.activeForm) {
			const ability = this.getFormAbility(this.activeForm);
			if (ability) {
				ability.panelAction(
					this.stepActions[this.activeForm].loadAction,
					'load',
					this.formParam
				);
			}
		}
	}

	/**
	 * 处理表单行为
	 *
	 * @param {string} name 表单标识
	 * @param {FormActionType} action 表单行为
	 * @param {IParam[]} data 行为数据
	 * @memberof WizardPanelController
	 */
	public handleCtrlAction(
		name: string,
		action: EditFormActionType,
		data: IParam[]
	): void {
		const arg = data[0];
		if (action === 'load' || action === 'loadDraft') {
			this.wizardpanelFormload(arg, name);
		}
		if (action === 'save') {
			this.wizardpanelFormsave(arg, name);
		}
	}

	/**
	 * 根据激活tag获取当前应该展示的编辑表单
	 *
	 * @param {string} activeForm 激活的wizard表单
	 * @return {*}
	 * @memberof WizardPanelController
	 */
	public getActiveEditForm(activeForm: string) {
		const editForm = (this.model.editForms || []).find((form: any) => {
			return form.name === activeForm;
		});
		if (editForm) {
			this.store.activeEditForm = editForm;
		}
	}

	/**
	 * 获取编辑表单能力
	 *
	 * @protected
	 * @return {*}  {(IEditFormAbility | undefined)}
	 * @memberof WizardPanelController
	 */
	public getFormAbility(name: string): IEditFormAbility | undefined {
		return this.getSubAbility<IEditFormAbility>(name);
	}

	/**
	 * 获取能力
	 *
	 * @return {*}  {IWizardPanelAbility}
	 * @memberof WizardPanelController
	 */
	getAbility(): IWizardPanelAbility {
		return {
			...super.getAbility(),
			load: this.load.bind(this),
		};
	}
}
